﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LuaInterface;
using NTUTMessagerAPI;
using System.IO;

namespace NTUTMessager
{
    public partial class BuddyListForm : Form
    {
        SocketAPI _socketApi;

        public BuddyListForm(SocketAPI socketApi)
        {
            //Console.WriteLine("3");
            _socketApi = socketApi;
           // Console.WriteLine("3");

            InitializeComponent();

            _socketApi.GetCommandEvent += getCommandEvent;
            _socketApi.ConnectListAddEvent += GetConnected;
            _socketApi.GetMessageEvent += getMessageEvent;
            _socketApi.GetByteEvent += getByteEvent;
            
        }

        public void getByteEvent(ConnectPair pair, Byte[] data)
        {

                        this.Invoke(new EventHandler(
                  delegate
                  {
                      Console.WriteLine(pair.address + " send " + data.Length + " betes data");

                      FileStream _FileStream = new FileStream(((PairData)(pair.UserData)).path, System.IO.FileMode.Create, System.IO.FileAccess.Write);

                      // Writes a block of bytes to this stream using data from a byte array.
                      _FileStream.Write(data, 0, data.Length);

                      // close file stream
                      _FileStream.Close();


                      CheckCommunicationWindows(pair);
                      CommunicationFormDictinary[pair.address].GetCommand("接收完成");
                      CommunicationFormDictinary[pair.address].Focus();

                  }));
  

        }

        public void getMessageEvent(ConnectPair pair, String command)
        {
            this.Invoke(new EventHandler(
                  delegate
                  {

                      CheckCommunicationWindows(pair);
                      CommunicationFormDictinary[pair.address].GetMessage(command);
                      CommunicationFormDictinary[pair.address].Focus();


                  }));
        }

        private void CheckCommunicationWindows(ConnectPair pair)
        {
            if (!CommunicationFormDictinary.ContainsKey(pair.address))
            {
                CommunicationForm form = new CommunicationForm(_socketApi, ((PairData)pair.UserData).account, pair.address);
                CommunicationFormDictinary.Add(pair.address, form);
                form.Show();
                form.FormClosed += FormClosedEventHandler;
            }
        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
  
        }

        public class PairData 
        {
            public string account;
            public string path;
        }

        public void GetConnected(ConnectPair pair) 
        {
            //Console.WriteLine(pair.address + " Connected");

            pair.UserData = new PairData();
           // ((PairData)pair.UserData).account = "unknown";

            for (int i = 0; i < dataGridView1.Rows.Count; i++)
            {
                if (dataGridView1.Rows[i].Cells[1].Value.ToString().Contains(pair.address) || pair.address.Contains(dataGridView1.Rows[i].Cells[1].Value.ToString()))
                {
                    //Console.WriteLine(dataGridView1.Rows[i].Cells[0].Value.ToString() + " Connected");

                    pair.UserData = new PairData();
                    ((PairData)pair.UserData).account = dataGridView1.Rows[i].Cells[0].Value.ToString();

                    pair.setRSA(Program.RSA_Parameters, dataGridView1.Rows[i].Cells[2].Value.ToString());

                    break;
                }
            }
        }

        

        public void getCommandEvent(ConnectPair pair, String command) 
        {
            FriendTableMethod(command);

            ChangeStateMethod(command);

            FileTransferStartMethod(pair,command);

            FileTransferingMethod(pair, command);
        }

        private void FileTransferingMethod(ConnectPair pair, String command)
        {
              Lua lua = new Lua();
            lua.DoString(command);
            LuaTable FileAcceptTable = lua.GetTable("FileAcceptTable");

            if (FileAcceptTable != null)
            {
                this.Invoke(new EventHandler(
                  delegate
                  {
                      if ((bool)FileAcceptTable["Result"])
                      {
                          CheckCommunicationWindows(pair);
                          CommunicationFormDictinary[pair.address].GetCommand("檔案傳送中......");
                          CommunicationFormDictinary[pair.address].Focus();

                          _socketApi.SendBytes(pair, GetBytesFromFile(CommunicationFormDictinary[pair.address].openDialog.FileName));


                          CheckCommunicationWindows(pair);
                          CommunicationFormDictinary[pair.address].GetCommand("傳送完成");
                          CommunicationFormDictinary[pair.address].Focus();
                      }
                      else 
                      {
                          CommunicationFormDictinary[pair.address].GetCommand("對方拒絕");
                      }

                  }
                    ));
            }
        }

        public static byte[] GetBytesFromFile(string fullFilePath)
        {

            FileStream fs = File.OpenRead(fullFilePath);
            try
            {
                byte[] bytes = new byte[fs.Length];
                fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
                fs.Close();
                return bytes;
            }
            finally
            {
                fs.Close();
            }
        }

        private void FileTransferStartMethod(ConnectPair pair,String command)
        {
            Lua lua = new Lua();
            lua.DoString(command);
            LuaTable FileTable = lua.GetTable("FileTable");
            if (FileTable != null)
            {
                this.Invoke(new EventHandler(
              delegate
              {

                  CheckCommunicationWindows(pair);
                  CommunicationFormDictinary[pair.address].GetCommand("對方欲傳送『"+(String)FileTable["FileName"]+"』，是否接收？");
                  CommunicationFormDictinary[pair.address].Focus();

                  SaveFileDialog saveDialog = new SaveFileDialog();
                  saveDialog.Filter = "All files (*.*)|*.*";
                  saveDialog.FilterIndex = 1;
                  saveDialog.RestoreDirectory = true;
                  saveDialog.FileName = (String)FileTable["FileName"];

                  if (saveDialog.ShowDialog() == DialogResult.OK)
                  {
                      _socketApi.SendCommand(pair, "FileAcceptTable = { [\"Result\"] = true }");
                      CommunicationFormDictinary[pair.address].GetCommand("確定接收至『" + saveDialog.FileName+ "』");
                      CommunicationFormDictinary[pair.address].GetCommand("檔案接收中.....");
                      ((PairData)(pair.UserData)).path = saveDialog.FileName;
                  }
                  else
                  {
                      _socketApi.SendCommand(pair, "FileAcceptTable = { [\"Result\"] = false }");
                      CommunicationFormDictinary[pair.address].GetCommand("拒絕接收");
                  }

              }));


            }
        }

        private void ChangeStateMethod(String command)
        {
            Lua lua = new Lua();
            lua.DoString(command);
            LuaTable friendStateTable = lua.GetTable("FriendStateTable");
            if (friendStateTable != null)
            {
                ChangeData(friendStateTable["account"].ToString(), friendStateTable["ip"].ToString(), friendStateTable["publicKey"].ToString());
            }
        }

        private void FriendTableMethod(String command)
        {
            Lua lua = new Lua();
            lua.DoString(command);
            LuaTable friendTable = lua.GetTable("FriendTable");
            if (friendTable != null)
            {
                foreach (LuaTable entry in friendTable.Values)
                {
                    AddData(entry["account"].ToString(), entry["ip"].ToString(), entry["publicKey"].ToString());
                }
            }
        }


        public void AddData(String str,String str2,String str3)
        {
            List<String> strList = new List<String>();

            strList.Add(str);
            strList.Add(str2);
            strList.Add(str3);

            this.Invoke(new EventHandler(
                 delegate
                 {
                     dataGridView1.Rows.Add(strList.ToArray()); // Entering with a "Step Into" here it crashes.
                 }
             ));

        }

        public void ChangeData(String account, String ip, String key)
        {
          this.Invoke(new EventHandler(
             delegate
             {
                 List<String> strList = new List<String>();

                 strList.Add(account);
                 strList.Add(ip);
                 strList.Add(key);

                 for (int i = 0; i < dataGridView1.Rows.Count; i++) 
                 {
                    // Console.WriteLine("scan:"+dataGridView1.Rows[i].Cells[0].Value.ToString());

                     if (dataGridView1.Rows[i].Cells[0].Value.ToString().Equals(account)) 
                     {
                         dataGridView1.Rows.RemoveAt(i);
                         dataGridView1.Rows.Insert(i, strList.ToArray());
                     }
                 }
             }
         ));

        }

        private void BuddyListForm_Load(object sender, EventArgs e)
        {
            _socketApi.SendCommand(0, "getFriend = {}");

            //int i = 0;

            //AddData("Irene", "192.136.123.12", "53");

            //while (i++ < 30)
            //{
            //    AddData("Test" + (i), "192.136.123.12" + (i), "53" + (i));
            //}
        }

        private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
         
        }

        private void dataGridView1_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            int rowIndex = e.RowIndex;

            if (rowIndex >= 0 && rowIndex < dataGridView1.Rows.Count) 
            {
                if (dataGridView1.Rows[rowIndex].Cells[1].Value.ToString().Equals("none"))
                {
                    MessageBox.Show(dataGridView1.Rows[rowIndex].Cells[0].Value.ToString() + " 此人不在線上!");
                }
                else 
                {
                    if (!CommunicationFormDictinary.ContainsKey(dataGridView1.Rows[rowIndex].Cells[1].Value.ToString()))
                    {
                        CommunicationForm form = new CommunicationForm(_socketApi, dataGridView1.Rows[rowIndex].Cells[0].Value.ToString(), dataGridView1.Rows[rowIndex].Cells[1].Value.ToString());
                        CommunicationFormDictinary.Add(dataGridView1.Rows[rowIndex].Cells[1].Value.ToString(), form);
                        form.Show();

                        form.FormClosed += FormClosedEventHandler;
                    }
                    else 
                    {
                        CommunicationFormDictinary[dataGridView1.Rows[rowIndex].Cells[1].Value.ToString()].Focus();
                    }
                }
            }
        }

        private void FormClosedEventHandler(object sender, FormClosedEventArgs e)
        {
            CommunicationFormDictinary.Remove(((CommunicationForm)sender)._ip);
        }

        Dictionary<String, CommunicationForm> CommunicationFormDictinary = new Dictionary<String, CommunicationForm>();
    }
}
